package com.kalvan.client.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.kalvan.client.constant.CommonReturnCode;
import com.kalvan.client.context.RequestContext;
import com.kalvan.client.context.RequestContextHolder;
import com.kalvan.client.exception.BizException;
import com.kalvan.client.exception.ReturnCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

/**
 * 开放API接口标准响应报文结构
 * 同步/异步
 *
 * @author chenliang
 */
@Getter
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Slf4j
public class ApiResponse<T> implements java.io.Serializable {
    static final long serialVersionUID = 1L;
    /**
     * 接入的appId
     */
    private String appId;
    /**
     * 返回数据
     * 需要加密为字符串
     */
    @Valid
    @NotNull(message = "data不能为空")
    private final Response<T> data;
    /**
     * 公钥加密过的AES key
     */
    private String key;
    /**
     * 响应签名
     */
    private String sign;

    private ApiResponse(Response response) {
        data = response;
    }

    /**
     * @param response Response
     * @return 返回结果对象
     */
    public static ApiResponse buildResult(Response response) {
        ApiResponse apiResponse = new ApiResponse(response);
        RequestContext context = RequestContextHolder.getContext();
        if (context != null) {
            apiResponse.setAppId(RequestContextHolder.getContext().appId);
        }
        return apiResponse;
    }

    /**
     * @param code 返回码
     * @param desc 返回描述
     * @return 返回结果对象
     */
    public static ApiResponse buildResult(String code, String desc) {
        return buildResult(Response.buildResult(code, desc));
    }

    /**
     * 根据返回码解析返回对象
     *
     * @param returnCode 返回码对象
     * @return 返回结果对象
     */
    public static ApiResponse buildResult(ReturnCode returnCode) {
        return buildResult(returnCode.getCode(), returnCode.getDesc());
    }

    /**
     * 根据biz异常解析返回对象
     *
     * @param exception bizException
     * @return 返回结果对象
     */
    public static ApiResponse buildResult(BizException exception) {
        return buildResult(exception.getCode(), exception.getDesc());
    }

    /**
     * 返回处理成功结果,默认使用0000
     *
     * @return 返回结果对象
     */
    public static ApiResponse buildSuccess() {
        return buildResult(CommonReturnCode.SUCCESS);
    }

    /**
     * 是否返回成功业务码,默认使用0000
     *
     * @return true /false
     */
    public boolean success() {
        return CommonReturnCode.SUCCESS.getCode().equals(data.getCode());
    }

    public ApiResponse setData(T data) {
        this.data.setData(data);
        return this;
    }

    public ApiResponse setAppId(String appId) {
        this.appId = appId;
        return this;
    }

    public ApiResponse setKey(String key) {
        this.key = key;
        return this;
    }

    public ApiResponse setSign(String sign) {
        this.sign = sign;
        return this;
    }

//    /**
//     * 异常失败返回不进行加密和签名
//     *
//     * @param response    HttpServletResponse
//     * @param apiResponse ApiResponse
//     */
//    public static void writerResponse(HttpServletResponse response, ApiResponse apiResponse) {
//        String msg = JSON.toJSONString(apiResponse);
//        log.info("异常响应报文:{}", msg);
//        RequestContext context = RequestContextHolder.getContext();
//        if (context != null) {
//            context.setResponseCode(apiResponse.getData().getCode());
//            context.setResponseDesc(apiResponse.getData().getDesc());
//        }
//        response.setCharacterEncoding("UTF-8");
//        response.setHeader("Content-Type", "application/json;charset=UTF-8");
//        try (PrintWriter writer = response.getWriter()) {
//            writer.print(msg);
//        } catch (Exception exception) {
//            log.error("响应异常", exception);
//        }
//    }

    @Override
    public String toString() {
        return "ApiResponse{" +
                "appId='" + appId + '\'' +
                ", data=" + data +
                ", key='" + key + '\'' +
                ", sign='" + sign + '\'' +
                '}';
    }
}
